const updater = require("./index");
const bar = require("./toolbar/controlbar");
const teminal = require("./toolbar/teminal");

const tryTime = 100;

let client = {
    state: true,
    tryTime: 0,
    manager: null,
    start(manager) {
        let context = manager._context;
        this.manager = manager;
        if (context.window.EventSource) {
            context.window.addEventListener("load", () => {
                bar.start(context);
                teminal.init(context);
                this.tryTime = 0;
                let source = this.source = new context.window.EventSource('/ada/sse');
                source.addEventListener('message', (e) => this.onmessage(e));
                source.addEventListener('error', (e) => this.onerror(e));
            });
            let MutationObserver = context.window.MutationObserver || context.window.WebKitMutationObserver || context.window.MozMutationObserver;
            if (MutationObserver) {
                new MutationObserver((mutations) => {
                    let has = false;
                    mutations.forEach((mutation) => {
                        [...mutation.removedNodes].forEach(target => {
                            if (target.querySelectorAll && target.querySelectorAll(".ada-hmr-controllbar").length > 0) {
                                has = true;
                            }
                            if (!has) {
                                has = target.classList ? target.classList.contains("ada-hmr-controllbar") : false;
                            }
                        });
                    });
                    if (has) {
                        bar.start(context);
                        teminal.init();
                    }
                }).observe(context.document, { childList: true, subtree: true });
            } else {
                context.document.body.addEventListener("DOMNodeRemoved", (e) => {
                    let target = e.target, has = false;
                    if (target.querySelectorAll && target.querySelectorAll(".ada-hmr-controllbar").length > 0) {
                        has = true;
                    }
                    if (!has) {
                        has = target.classList ? target.classList.contains("ada-hmr-controllbar") : false;
                    }
                    if (has) {
                        bar.start(context);
                        teminal.init();
                    }
                });
            }
        }
    },
    onmessage(e) {
        this.tryTime = 0;
        let manager = this.manager;
        let context = this.manager._context;
        let data = JSON.parse(e.data), log = data.log;
        let app = data.app, _context = manager.getContext('root');
        teminal.showError(_context, app, log || []);
        if (log && log.length === 0 && bar.getState(_context)) {
            if (data.type === "edit") {
                bar.actionStart();
                let targetContext = manager.getContext(app);
                if (targetContext) {
                    updater.refresh(targetContext, data.files, data.map, this.manager).then(() => {
                        bar.actionDone();
                    }).catch((e) => {
                        console.error(e);
                        context.window.location.reload();
                    });
                }
            } else if (data.type !== "start") {
                context.window.location.reload();
            }
        } else {
            console.log(`%c[Ada] HMR is stopped`, "color:#3D78A7;font-weight:bold");
        }
        if (data.type === "reload") {
            context.window.location.reload();
        }
    },
    onerror() {
        if (this.tryTime === tryTime) {
            this.source.close();
            console.log("%c- [Ada] HMR sse is closed,Try to reload page when needed", "color:#3D78A7;font-weight:bold");
        } else {
            if (this.tryTime === 0) {
                console.log("%c- [Ada] HMR sse is closed", "color:#3D78A7;font-weight:bold");
            }
            this.tryTime++;
        }
    }
};

module.exports = {
    client,
    status() {
        return bar.isRunning(context);
    },
    hideControllbar() {
        bar.hide();
    },
    showControllbar() {
        bar.show();
    }
};